
import CustomClass.*;
import ObjectManager.*;
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

public class PlayGameCanvas extends GameCanvas implements Runnable, CommandListener {
    Command cmdExit, cmdPauseResume;
    boolean isPlay, isPause;
    Timer myTimer, timer_AppearPoliceCar, timer_AppearMoney, timer_AppearPeople;
    int viewMargin_Left = 0, viewMargin_Top = 0, margin_Left = 0, margin_Right = 0;
    //layer & object game
    LayerManager layerManager;
    LayerManager layerManager_Left;
    Car playerCar, policeCar = null;
    AnimationObject explode, explodePoliceCar;
    Terrain currentTerrain;
    InsertCarTimerTask insertCarTimerTask;
    AppearPoliceCarTimerTask appearPoliceCarTimerTask;
    InsertMoneyTimerTask insertMoneyTimerTask;
    InsertPeopleTimerTask inserPeopleTimerTask;
    int insertCarDelay;
    Car[] lstEnemyCar;
    AnimationObject[] lstMoney;
    AnimationObject[] lstPerson;
    int currentTotalEnemyCar = 0;
    int currentTotalMoney = 0;
    int currentTotalPerson = 0;
    //Stages Info
    StageInfo[] arrStageInfo;
    int curStage;
    Graphics g;
    //Map
    Map map;
    SoundHelper soundHelper, soundExplode, soundPhanh, soundGetItem, soundCollidePeople;
    //NhienLieu
    float currentFuel;
    int numberOfFuel;
    //Tien
    int totalMoney = 0;
    //int life = 3;
    private MidletDuaXe midlet;
    private Display display;

    Random r;
    public PlayGameCanvas(MidletDuaXe midlet) {
        super(true);
        
        cmdPauseResume = new Command("Pause", Command.OK, 0);
        addCommand(cmdPauseResume);
        
        cmdExit = new Command("Exit", Command.EXIT, 0);
        addCommand(cmdExit);
        
        setCommandListener(this);
        this.midlet = midlet;
//        this.display = display;
        viewMargin_Left = 30;
        viewMargin_Top = 0;

        g = getGraphics();

        curStage = 0;
        InitStagesInfo();

        //Init timer
        myTimer = new Timer();
        insertCarTimerTask = new InsertCarTimerTask();
        insertCarDelay = arrStageInfo[curStage].insertCarDelay;

        timer_AppearPoliceCar = new Timer();
        appearPoliceCarTimerTask = new AppearPoliceCarTimerTask();


        lstEnemyCar = new Car[10];

        //Init money
        timer_AppearMoney = new Timer();
        insertMoneyTimerTask = new InsertMoneyTimerTask();
        lstMoney = new AnimationObject[10];

        //Init people
        timer_AppearPeople = new Timer();
        inserPeopleTimerTask = new InsertPeopleTimerTask();
        lstPerson = new AnimationObject[10];

        //soundHelper
//        soundHelper = new SoundHelper("Sound/mortal_kombat.mid");
//        soundHelper.setLoopCount(-1);
//        soundExplode = new SoundHelper("Sound/Explode.wav", "audio/wav");
//        soundExplode.setLoopCount(1);
//        soundPhanh = new SoundHelper("Sound/Phanh.wav", "audio/wav");
//        soundPhanh.setLoopCount(1);
//        soundGetItem = new SoundHelper("Sound/GetItem.wav", "audio/wav");
//        soundGetItem.setLoopCount(1);
//        soundCollidePeople = new SoundHelper("Sound/DungNguoi.wav", "audio/wav");
//        soundCollidePeople.setLoopCount(1);

        //playerCar
        playerCar = new Car("/Images/RedCar.PNG", 23, 48);
        playerCar.SetCurrentPos((getWidth() - playerCar.width) / 2, getHeight() - playerCar.height - 30);

        //explode
        explode = new AnimationObject(64, 64, "/Images/explode.png", 20);
        explodePoliceCar = new AnimationObject(64, 64, "/Images/explode.png", 20);

        //currentTerrain
        arrStageInfo[curStage].tiledBackground = InitTiledBackground(arrStageInfo[curStage].tileBg,
                arrStageInfo[curStage].tileData,
                arrStageInfo[curStage].totalRows, arrStageInfo[curStage].totalCols,
                arrStageInfo[curStage].tileWidth, arrStageInfo[curStage].tileHeight);
        currentTerrain = new Terrain(arrStageInfo[curStage].tiledBackground, arrStageInfo[curStage].arrObjectGame);
        numberOfFuel = arrStageInfo[curStage].numberOfFuel;
        for (int i = 1; i <= numberOfFuel; i++) {
            currentTerrain.arrObjectGame[i].xet = true;
            ((AnimationObject) currentTerrain.arrObjectGame[i]).Start(true);
        }
        currentTerrain.Move(0, getHeight() - currentTerrain.height);

        //map
        map = new Map("/Images/map_stage1.PNG", 10, 150);
        map.SetCurrentPos(10, 10);

        //layerManager_Left
        layerManager_Left = new LayerManager();
        layerManager_Left.append(map.carSprite);
        layerManager_Left.append(map.objSprite);

        //layerManager
        layerManager = new LayerManager();
        layerManager.append(playerCar.objSprite);
        for (int i = 0; i < currentTerrain.arrObjectGame.length; i++) {
            layerManager.append(currentTerrain.arrObjectGame[i].objSprite);
        }
        layerManager.append(currentTerrain.tiledBackground);

        //
        currentFuel = arrStageInfo[curStage].fuel;


        //
        r = new Random();
    }

    private void Init() {
        if (curStage > 0) {
            if(arrStageInfo[curStage - 1] != null){
                for(int i = 1; i < arrStageInfo[curStage - 1].arrObjectGame.length; i++){
                    if(arrStageInfo[curStage - 1].arrObjectGame[i] != null){
                        ((AnimationObject)arrStageInfo[curStage - 1].arrObjectGame[i]).Stop();
                    }
                }
                arrStageInfo[curStage - 1].tiledBackground = null;
                arrStageInfo[curStage - 1] = null;
            }
            if(currentTerrain != null){
                for(int i = 1; i < currentTerrain.arrObjectGame.length; i++){
                    if(currentTerrain.arrObjectGame[i] != null){
                        ((AnimationObject)currentTerrain.arrObjectGame[i]).Stop();
                    }
                }
                currentTerrain = null;
            }
            System.gc();
        }

        //Money
        for(int i = 0; i < currentTotalMoney; i++){
            lstMoney[i].Stop();
            lstMoney[i]= null;
        }
        lstMoney = new AnimationObject[10];
        timer_AppearMoney = new Timer();
        insertMoneyTimerTask = new InsertMoneyTimerTask();
        currentTotalMoney = 0;

        //People
        for(int i = 0; i < currentTotalPerson; i++){
            lstPerson[i].Stop();
            lstPerson[i]= null;
        }
        lstPerson = new AnimationObject[10];
        timer_AppearPeople = new Timer();
        inserPeopleTimerTask = new InsertPeopleTimerTask();
        currentTotalPerson = 0;

        myTimer = new Timer();
        insertCarTimerTask = new InsertCarTimerTask();

        timer_AppearPoliceCar = new Timer();
        appearPoliceCarTimerTask = new AppearPoliceCarTimerTask();

        lstEnemyCar = new Car[10];
        currentTotalEnemyCar = 0;

        //playerCar
        playerCar.SetCurrentPos((getWidth() - playerCar.width) / 2, getHeight() - playerCar.height - 30);

        //policeCar
        policeCar = null;

        //currentTerrain
        arrStageInfo[curStage].tiledBackground = InitTiledBackground(arrStageInfo[curStage].tileBg,
                arrStageInfo[curStage].tileData,
                arrStageInfo[curStage].totalRows, arrStageInfo[curStage].totalCols,
                arrStageInfo[curStage].tileWidth, arrStageInfo[curStage].tileHeight);
        currentTerrain = new Terrain(arrStageInfo[curStage].tiledBackground, arrStageInfo[curStage].arrObjectGame);
        currentTerrain.arrObjectGame[0].SetCurrentPos(0, 20);
        insertCarDelay = arrStageInfo[curStage].insertCarDelay;

        //
        Random r = new Random();
        int randy = 1000;
        //Khoi tao
        margin_Left = arrStageInfo[curStage].margin_Left;
        margin_Right = arrStageInfo[curStage].margin_Right;
        currentFuel = arrStageInfo[curStage].fuel;
        numberOfFuel = arrStageInfo[curStage].numberOfFuel;
        for (int i = 1; i <= numberOfFuel; i++) {
            currentTerrain.arrObjectGame[i].xet = true;
            ((AnimationObject) currentTerrain.arrObjectGame[i]).Start(true);
            currentTerrain.arrObjectGame[i].SetCurrentPos(margin_Left + r.nextInt(getWidth() - margin_Left - margin_Right - 60), randy);
            randy += ((int) r.nextInt(4) + 2) * 100;
        }


        //

        currentTerrain.SetCurPos(0, getHeight() - currentTerrain.height);
        //map
        map.SetCurrentPos(10, 10);

        //layerManager_Left
        layerManager_Left = new LayerManager();
        layerManager_Left.append(map.carSprite);
        layerManager_Left.append(map.objSprite);

        //layerManager
        layerManager = new LayerManager();
        layerManager.append(playerCar.objSprite);

        for (int i = 0; i < currentTerrain.arrObjectGame.length; i++) {
            layerManager.append(currentTerrain.arrObjectGame[i].objSprite);
        }

        layerManager.append(currentTerrain.tiledBackground);



    }

    private void InitStagesInfo() {
        arrStageInfo = new StageInfo[3];

        ObjectGame objGoal = null;
        Random r = new Random();
        int randy = 1000;
        //Tao thong tin cho cac man
        //Man 1, chi so 0
        margin_Left = 22;
        margin_Right = 40;
        //Create tileLayer Level 1
        int tileDataLv1[] = {
            2,
            1,
            1,
            3,
            1,
            1,
            1,
            4,
            1,
            1,
            1,
            1,
            3,
            1,
            1,
            1,
            1,
            4,
            1,
            1,
            1,
            1,
            1,
            1,
            3,
            1,
            1,
            1,
            1,
            1,
            1,
            4,
            1,
            1,
            1,
            3,
            1,
            1,
            1,
            1,
            4,
            1,
            1,
            1,
            1,
            3,
            1,
            1,
            1,
            1,
            1,
            1,
            3,
            1,
            1,
            1,
            4,
            1,
            1,
            1,
            1,
            1,
            3,
            1,
            1,
            1,
            1,
            2
        };
        String tileBgLv1 = "/Images/bg_stage1.PNG";

        //Khoi tao danh sach cac object tren duong dua
        ObjectGame[] arrObjectGameLv1 = new ObjectGame[16];

        //Khoi tao goal
        objGoal = new ObjectGame("/Images/Goal.png", 240, 22, ObjectGameType.GOAL);
        objGoal.SetCurrentPos(0, 20);
        arrObjectGameLv1[0] = objGoal;

        //Khoi tao vi tri cac binh xang
        numberOfFuel = 15;
        for (int i = 1; i <= numberOfFuel; i++) {
            arrObjectGameLv1[i] = new AnimationObject(25, 25, "/Images/Fuel.png", 100);
            arrObjectGameLv1[i].objGameType = ObjectGameType.FUEL;
            arrObjectGameLv1[i].SetCurrentPos(margin_Left + r.nextInt(getWidth() - margin_Left - margin_Right - 60), randy);
            randy += ((int) r.nextInt(4) + 2) * 100;
        }
        //Khoi tao man choi
        arrStageInfo[0] = new StageInfo(1, 3000, 3, tileDataLv1, tileBgLv1, arrObjectGameLv1, 100,
                numberOfFuel, 20, margin_Left, margin_Right,
                68, 1, 210, 100);


        //Man 1, chi so 1
        randy = 1000;
        margin_Left = 29;
        margin_Right = 58;
        //Create tileLayer Level 2
        int tileDataLv2[] = {
            2,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            2
        };

        String tileBgLv2 = "/Images/bg_stage2.png";
        //Khoi tao danh sach cac object tren duong dua
        ObjectGame[] arrObjectGameLv2 = new ObjectGame[21];

        //Khoi tao goal
        objGoal = new ObjectGame("/Images/Goal.png", 240, 22, ObjectGameType.GOAL);
        objGoal.SetCurrentPos(0, 20);
        arrObjectGameLv2[0] = objGoal;

        //Khoi tao vi tri cac binh xang
        //currentFuel = arrStageInfo[1].fuel;
        numberOfFuel = 20;
        for (int i = 1; i <= numberOfFuel; i++) {
            arrObjectGameLv2[i] = new AnimationObject(25, 25, "/Images/Fuel.png", 100);
            arrObjectGameLv2[i].objGameType = ObjectGameType.FUEL;
            arrObjectGameLv2[i].SetCurrentPos(margin_Left + r.nextInt(getWidth() - margin_Left - margin_Right - 60), randy);
            randy += ((int) r.nextInt(4) + 2) * 100;
        }

        //Khoi tao man choi
        arrStageInfo[1] = new StageInfo(2, 2500, 4, tileDataLv2, tileBgLv2, arrObjectGameLv2, 100,
                numberOfFuel, 40, margin_Left, margin_Right,
                40, 1, 210, 244);

        //
        // Man 3 ,chi so 2
        randy = 1000;
        margin_Left = 29;
        margin_Right = 58;
        //Create tileLayer Level 2
        int tileDataLv3[] = {
            1,
            2,
            2,
            2,
            3,
            3,
            2,
            2,
            3,
            2,
            2,
            2,
            3,
            3,
            3,
            3,
            2,
            2,
            2,
            2,
            3,
            3,
            3,
            3,
            3,
            2,
            2,
            2,
            3,
            3,
            2,
            2,
            2,
            2,
            2,
            3,
            3,
            3,
            2,
            2,
            3,
            3,
            3,
            2,
            2,
            1
        };
        String tileBgLv3 = "/Images/bg_stage4.png";

        //Khoi tao danh sach cac object tren duong dua
        ObjectGame[] arrObjectGameLv3 = new ObjectGame[24];

        //Khoi tao goal
        objGoal = new ObjectGame("/Images/Goal.png", 240, 22, ObjectGameType.GOAL);
        objGoal.SetCurrentPos(0, 20);
        arrObjectGameLv3[0] = objGoal;


        //Khoi tao vi tri cac binh xang
        //currentFuel = arrStageInfo[2].fuel;
        numberOfFuel = 23;
        for (int i = 1; i <= numberOfFuel; i++) {
            arrObjectGameLv3[i] = new AnimationObject(25, 25, "/Images/Fuel.png", 100);
            arrObjectGameLv3[i].objGameType = ObjectGameType.FUEL;
            arrObjectGameLv3[i].SetCurrentPos(margin_Left + r.nextInt(getWidth() - margin_Left - margin_Right - 60), randy);
            randy += ((int) r.nextInt(4) + 2) * 100;
        }
        //Khoi tao man choi
        arrStageInfo[2] = new StageInfo(3, 2000, 5, tileDataLv3, tileBgLv3, arrObjectGameLv3, 100,
                numberOfFuel, 60, margin_Left, margin_Right,
                46, 1, 210, 223);
    }

    public void Start() {
        isPlay = true;
        isPause = false;
        //soundHelper
        soundHelper = new SoundHelper("Sound/mortal_kombat.mid");
        soundHelper.setLoopCount(-1);
        soundExplode = new SoundHelper("Sound/Explode.wav", "audio/wav");
        soundExplode.setLoopCount(1);
        soundPhanh = new SoundHelper("Sound/Phanh.wav", "audio/wav");
        soundPhanh.setLoopCount(1);
        soundGetItem = new SoundHelper("Sound/GetItem.wav", "audio/wav");
        soundGetItem.setLoopCount(1);
        soundCollidePeople = new SoundHelper("Sound/DungNguoi.wav", "audio/wav");
        soundCollidePeople.setLoopCount(1);
        Thread t = new Thread(this);
        t.start();
    }

    public void run() {
        showReady();
        soundHelper.playSound();
        myTimer.schedule(insertCarTimerTask, 0, insertCarDelay);
        timer_AppearPoliceCar.schedule(appearPoliceCarTimerTask, 0, 3000);
        timer_AppearMoney.schedule(insertMoneyTimerTask, 0, 4000);
        timer_AppearPeople.schedule(inserPeopleTimerTask, 0, 6000);
        while (isPlay == true) {
            if(isPause){
                myTimer.cancel();
                timer_AppearPoliceCar.cancel();
                timer_AppearMoney.cancel();
                timer_AppearPeople.cancel();
                while(isPause)
                {
                    
                }
                timer_AppearMoney = new Timer();
                insertMoneyTimerTask = new InsertMoneyTimerTask();
                timer_AppearPeople = new Timer();
                inserPeopleTimerTask = new InsertPeopleTimerTask();
                myTimer = new Timer();
                insertCarTimerTask = new InsertCarTimerTask();
                timer_AppearPoliceCar = new Timer();
                appearPoliceCarTimerTask = new AppearPoliceCarTimerTask();
                myTimer.schedule(insertCarTimerTask, insertCarDelay, insertCarDelay);
                timer_AppearPoliceCar.schedule(appearPoliceCarTimerTask, 3000, 3000);
                timer_AppearMoney.schedule(insertMoneyTimerTask, 4000, 4000);
                timer_AppearPeople.schedule(inserPeopleTimerTask, 6000, 6000);
            }
            else{
                input();
                if(isPlay){
                    if (policeCar != null) {
                        UpdatePoliceCar(policeCar);
                    }
                    UpdateEnemyCarPos();
                    UpdateMoneyPos();
                    UpdatePeoplePos();
                    drawScreen(g);
                    try {
                        Thread.sleep(20);
                    } 
                    catch (InterruptedException ie) {
                    }
                }
            }
        }

    }
    int life = 3;

    private void drawScreen(Graphics g) {
        g.setColor(0x017728);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0xff0000);

        if (playerCar.currentX <= margin_Left) {
            playerCar.SetCurrentX(margin_Left + 2);
        } else if (playerCar.currentX + playerCar.width >= getWidth() - margin_Right) {
            playerCar.SetCurrentX(getWidth() - (playerCar.width + margin_Right + 2));
        }


        //Check car collide with GOAL or Fuel
        for (int i = 0; i < currentTerrain.arrObjectGame.length; i++) {
            if (playerCar.objSprite.collidesWith(currentTerrain.arrObjectGame[i].objSprite, false)) {
                if (currentTerrain.arrObjectGame[i].objGameType == ObjectGameType.GOAL) {
                    layerManager.paint(g, viewMargin_Left, viewMargin_Top);
                    layerManager_Left.paint(g, 0, 0);
                    try {
                        Image img = Image.createImage("/Images/box.png");
                        g.drawImage(img, 45 + viewMargin_Left, 100, Graphics.LEFT | Graphics.TOP);
                        img = Image.createImage("/Images/Goal_Text.png");
                        g.drawImage(img, 60 + viewMargin_Left, 120 + viewMargin_Top, Graphics.LEFT | Graphics.TOP);
                    } catch (Exception ex) {
                    }
                    flushGraphics();
                    myTimer.cancel();
                    timer_AppearMoney.cancel();
                    timer_AppearPoliceCar.cancel();
                    timer_AppearPeople.cancel();
                    isPlay = false;
                    try {
                        Thread.sleep(2000);
                    } catch (Exception ex) {
                    }
                    curStage++;
                    if (curStage < arrStageInfo.length) {
                        Init();
                        isPlay = true;
                        layerManager.paint(g, viewMargin_Left, viewMargin_Top);
                        layerManager_Left.paint(g, 0, 0);
                        showReady();
                        myTimer.schedule(insertCarTimerTask, 0, insertCarDelay);
                        timer_AppearMoney.schedule(insertMoneyTimerTask, 0, 4000);
                        timer_AppearPoliceCar.schedule(appearPoliceCarTimerTask, 0, 3000);
                        timer_AppearPeople.schedule(inserPeopleTimerTask, 0, 6000);
                    }
                    else{
                        isPlay = false;
                        showWinner();
                        flushGraphics();
                    }
                    return;
                }
                if (currentTerrain.arrObjectGame[i].objGameType == ObjectGameType.FUEL) {
                    if (currentTerrain.arrObjectGame[i].xet) {
                        currentTerrain.arrObjectGame[i].xet = false;
                        AnimationObject animeObj = (AnimationObject) currentTerrain.arrObjectGame[i];
                        animeObj.Stop();
                        layerManager.remove(animeObj.objSprite);
                        soundGetItem.playSound();
                        currentFuel += 25;
                        if (currentFuel > arrStageInfo[curStage].fuel) {
                            currentFuel = arrStageInfo[curStage].fuel;
                        }
                        break;
                    }
                }

            }
        }

        if (policeCar != null) {
            //Check collision between police car and enemy cars
            for (int i = 0; i < currentTotalEnemyCar; i++) {
                if (policeCar.objSprite.collidesWith(lstEnemyCar[i].objSprite, false)) {
                    explodePoliceCar.SetCurrentPos(policeCar.currentX - explodePoliceCar.width / 2 + 5, policeCar.currentY - 10);
                    layerManager.remove(policeCar.objSprite);
                    policeCar = null;
                    layerManager.insert(explodePoliceCar.objSprite, 0);
                    explodePoliceCar.Start(false);
                    soundExplode.playSound();
                    break;
                }
            }
        }

        //Collision with police car
        if (policeCar != null) {
            if (playerCar.objSprite.collidesWith(policeCar.objSprite, false)) {
                soundPhanh.playSound();
                if (policeCar.currentX > playerCar.currentX) {
                    playerCar.SetCurrentX(Math.max(arrStageInfo[curStage].margin_Left, playerCar.currentX - 10));
                } else {
                    playerCar.SetCurrentX(Math.min(getWidth() - viewMargin_Left - playerCar.width - arrStageInfo[curStage].margin_Right, playerCar.currentX + 10));
                }
            }
        }
        //Collision with money
        for (int i = 0; i < currentTotalMoney; i++) {
            if (playerCar.objSprite.collidesWith(lstMoney[i].objSprite, false)) {
                totalMoney += 1;
                lstMoney[i].Stop();
                soundGetItem.playSound();
                layerManager.remove(lstMoney[i].objSprite);
                for (int j = i; j < currentTotalMoney - 1; j++) {
                    lstMoney[j] = lstMoney[j + 1];
                }
                currentTotalMoney--;
                break;
            }
        }
        //Collision with people
        for (int i = 0; i < currentTotalPerson; i++) {
            if (playerCar.objSprite.collidesWith(lstPerson[i].objSprite, false)) {
                if(totalMoney > 0) totalMoney -= 1;
                lstPerson[i].Stop();
                soundCollidePeople.playSound();
                layerManager.remove(lstPerson[i].objSprite);
                for (int j = i; j < currentTotalPerson - 1; j++) {
                    lstPerson[j] = lstPerson[j + 1];
                }
                lstPerson[currentTotalPerson - 1] = null;
                currentTotalPerson--;
                break;
            }
        }

        //
        for (int i = 0; i < currentTotalEnemyCar; i++) {
            //Collision with other car
            if (playerCar.objSprite.collidesWith(lstEnemyCar[i].objSprite, false) || currentFuel < 0) {
                life--;
                myTimer.cancel();
                timer_AppearMoney.cancel();
                timer_AppearPoliceCar.cancel();
                timer_AppearPeople.cancel();
                explode.SetCurrentPos(playerCar.currentX - explode.width / 2 + 5, playerCar.currentY - 10);
                layerManager.remove(playerCar.objSprite);
                layerManager.insert(explode.objSprite, 0);
                explode.Start(false);
                soundExplode.playSound();
                while (explode.isRunning) {
                    layerManager.paint(g, viewMargin_Left, viewMargin_Top);
                    layerManager_Left.paint(g, 0, 0);
                    flushGraphics();
                }
                layerManager.paint(g, viewMargin_Left, viewMargin_Top);
                layerManager_Left.paint(g, 0, 0);
                if (life == 0) {
                    isPlay = false;
                    showGameOver();
                    return;
                }
                try {
                    Image img = Image.createImage("/Images/box.png");
                    g.drawImage(img, 45 + viewMargin_Left, 100, Graphics.LEFT | Graphics.TOP);
                    img = Image.createImage("/Images/Lose_Text.png");
                    g.drawImage(img, 60 + viewMargin_Left, 120 + viewMargin_Top, Graphics.LEFT | Graphics.TOP);
                    g.drawString("Press ENTER \n to replay", 60 + viewMargin_Left, 170 + viewMargin_Top, Graphics.LEFT | Graphics.TOP);
                } catch (Exception ex) {
                }
                flushGraphics();
                while (true) {
                    if (getKeyStates() == FIRE_PRESSED) {
                        Init();
                        showReady();
                        myTimer.schedule(insertCarTimerTask, 0, insertCarDelay);
                        timer_AppearMoney.schedule(insertMoneyTimerTask, 0, 4000);
                        timer_AppearPoliceCar.schedule(appearPoliceCarTimerTask, 0, 3000);
                        timer_AppearPeople.schedule(inserPeopleTimerTask, 0, 6000);
                        break;
                    }
                }
                return;
            }
            layerManager.paint(g, viewMargin_Left, viewMargin_Top);
            layerManager_Left.paint(g, 0, 0);
            g.drawString("P " + Float.toString(currentFuel), 1, 230, Graphics.LEFT | Graphics.TOP);
            g.drawString("M " + Integer.toString(totalMoney), 1, 220, Graphics.LEFT | Graphics.TOP);
            g.drawString("L " + Integer.toString(curStage + 1), 1, 210, Graphics.LEFT | Graphics.TOP);
            try {
                Image imgCarLife = Image.createImage("/Images/MiniRedCar.PNG");
                g.drawImage(imgCarLife, 3, 250, Graphics.LEFT | Graphics.TOP);
                g.drawString("x " + Integer.toString(life), 18, 250, Graphics.LEFT | Graphics.TOP);
            } catch (Exception ex) {
            }
            flushGraphics();
        }
    }

    private void input() {
        int keyStates = getKeyStates();
        
        // Left
        if ((keyStates & LEFT_PRESSED) != 0) {
            if (policeCar != null) {
                if (!policeCar.objSprite.collidesWith(playerCar.objSprite, false) || policeCar.currentX > playerCar.currentX) {
                    playerCar.SetCurrentX(Math.max(0, playerCar.currentX - playerCar.speed));
                }
            }
            else
                playerCar.SetCurrentX(Math.max(0, playerCar.currentX - playerCar.speed));
        }

        // Right
        if ((keyStates & RIGHT_PRESSED) != 0) {
            if (policeCar != null) {
                if (!policeCar.objSprite.collidesWith(playerCar.objSprite, false) || policeCar.currentX < playerCar.currentX) {
                    playerCar.SetCurrentX(Math.min(getWidth() - viewMargin_Left - playerCar.width, playerCar.currentX + playerCar.speed));
                }
            }
            else
                playerCar.SetCurrentX(Math.min(getWidth() - viewMargin_Left - playerCar.width, playerCar.currentX + playerCar.speed));
        }

        // Up
        if ((keyStates & UP_PRESSED) != 0) {
            playerCar.SetCurrentY(Math.max(0, playerCar.currentY - playerCar.speed));
        }

        if (currentTerrain.currentY >= 0) {
            playerCar.SetCurrentY(Math.max(0, playerCar.currentY - playerCar.speed));
            return;
        } else {
            currentTerrain.Move(0, Math.min(-currentTerrain.currentY, playerCar.speed));
        }

        //Down
        if ((keyStates & DOWN_PRESSED) != 0) {
            playerCar.SetCurrentY(Math.min(getHeight() - viewMargin_Top - playerCar.height, playerCar.currentY + playerCar.speed));
        }

        map.SetMiniCarCurrentY((-currentTerrain.currentY + playerCar.currentY) * map.height / currentTerrain.height);
        currentFuel -= 0.25;
    }

    private void UpdateEnemyCarPos() {
        for (int i = 0; i < currentTotalEnemyCar; i++) {
            lstEnemyCar[i].currentY += lstEnemyCar[i].speed;
            if (Math.abs(lstEnemyCar[i].currentY - playerCar.currentY) < 100) {
                if (lstEnemyCar[i].currentX < playerCar.currentX) {
                    lstEnemyCar[i].currentX += 1;
                } else {
                    lstEnemyCar[i].currentX -= 1;
                }
            }
            if (lstEnemyCar[i].currentY < getHeight() + 10) {
                lstEnemyCar[i].SetCurrentPos(lstEnemyCar[i].currentX, lstEnemyCar[i].currentY);
            } else {
                //Remove enemy car out of lstEnemyCar because it goes out screen
                for (int j = i; j < currentTotalEnemyCar - 1; j++) {
                    lstEnemyCar[j] = lstEnemyCar[j + 1];
                }
                lstEnemyCar[currentTotalEnemyCar - 1] = null;
                currentTotalEnemyCar -= 1;
                i--;
            }
        }
    }

    private void UpdateMoneyPos() {
        try {
            for (int i = 0; i < currentTotalMoney; i++) {
                lstMoney[i].currentY += arrStageInfo[curStage].carSpeed;
                if (lstMoney[i].currentY < getHeight() + 10) {
                    lstMoney[i].SetCurrentPos(lstMoney[i].currentX, lstMoney[i].currentY);
                } else {
                    //Remove money
                    for (int j = i; j < currentTotalMoney - 1; j++) {
                        lstMoney[j] = lstMoney[j + 1];
                    }
                    lstMoney[currentTotalMoney - 1].Stop();
                    lstMoney[currentTotalMoney - 1] = null;
                    currentTotalMoney -= 1;
                    i--;
                }
            }
        } catch (Exception ex) {
        }
    }

    private void UpdatePoliceCar(Car policeCar) {
        Car enemy = lstEnemyCar[0];
        if (enemy != null) {
            if (enemy.currentX < playerCar.currentX) {
                if (policeCar.currentX > playerCar.currentX && playerCar.currentX > 0) {
                    if (policeCar.currentY > playerCar.currentY) {
                        policeCar.SetCurrentY(policeCar.currentY - policeCar.speed);
                    } else {
                        policeCar.SetCurrentX(policeCar.currentX - policeCar.speed);
                    }
                } else {
                    if (policeCar.currentY < playerCar.currentY + playerCar.height) {
                        policeCar.SetCurrentY(policeCar.currentY + policeCar.speed);
                    } else {
                        policeCar.SetCurrentX(policeCar.currentX + policeCar.speed);
                    }
                }
            }
            if (enemy.currentX > playerCar.currentX) {
                if (policeCar.currentX < playerCar.currentX && playerCar.currentX < getWidth() - viewMargin_Left - playerCar.width) {
                    if (policeCar.currentY > playerCar.currentY) {
                        policeCar.SetCurrentY(policeCar.currentY - policeCar.speed);
                    } else {
                        policeCar.SetCurrentX(policeCar.currentX + policeCar.speed);
                    }
                } else {
                    if (policeCar.currentY < playerCar.currentY + playerCar.height) {
                        policeCar.SetCurrentY(policeCar.currentY + policeCar.speed);
                    } else {
                        policeCar.SetCurrentX(policeCar.currentX - policeCar.speed);
                    }
                }
            }
        }
    }

    public void commandAction(Command c, Displayable d) {
        if(c == cmdExit)
            this.midlet.destroyApp(true);
        else{
            this.removeCommand(this.cmdPauseResume);
            if("Pause".equals(this.cmdPauseResume.getLabel())){
                this.cmdPauseResume = new Command("Resume", Command.OK, 0);
                isPause = true;
            }
            else{
                this.cmdPauseResume = new Command("Pause", Command.OK, 0);
                isPause = false;
            }
            this.addCommand(this.cmdPauseResume);
        }
    }

    private class InsertCarTimerTask extends TimerTask {

        String[] arrImgSrc = {"/Images/BlueCar.PNG", "/Images/SilverCar.PNG", "/Images/YellowCar.PNG"};
        int[] arrWidthCar = {22, 22, 23};
        int[] arrHeightCar = {48, 48, 48};

        public final void run() {
            Car newCar = GetRandomCar();
            newCar.speed = arrStageInfo[curStage].carSpeed;
            Random r = new Random();
            int x = 0;
            while (x <= margin_Left) {
                x = r.nextInt(getWidth() - viewMargin_Left - 22 - margin_Right);
            }
            newCar.currentX = x;
            newCar.currentY = newCar.height - getHeight() - viewMargin_Top;
            lstEnemyCar[currentTotalEnemyCar++] = newCar;
            layerManager.insert(newCar.objSprite, 0);
        }

        private Car GetRandomCar() {
            
            int randomIndex = r.nextInt(arrImgSrc.length);
            String imgSrc = arrImgSrc[randomIndex];
            return new Car(imgSrc, arrWidthCar[randomIndex], arrHeightCar[randomIndex]);
        }
    }

    private class AppearPoliceCarTimerTask extends TimerTask {

        public void run() {
            if (policeCar == null) {
                Random r = new Random();
                if (r.nextInt(100) < arrStageInfo[curStage].percentAppearPoliceCar) {
                    policeCar = new Car("/Images/PoliceCar.PNG", 23, 48);
                    policeCar.SetCurrentPos((getWidth() - policeCar.width) / 2, getHeight());
                    policeCar.speed = 5;
                    layerManager.insert(policeCar.objSprite, 0);
                }
            }
        }
    }

    private class InsertMoneyTimerTask extends TimerTask {

        public final void run() {
            AnimationObject money = new AnimationObject(25, 25, "/Images/Money.png", 100);
            money.Start(true);
            
            int x = 0;
            while (x <= margin_Left) {
                x = r.nextInt(getWidth() - viewMargin_Left - 22 - margin_Right);
            }
            money.currentX = x;
            money.currentY = money.height - getHeight() - viewMargin_Top;
            lstMoney[currentTotalMoney++] = money;
            layerManager.insert(money.objSprite, 0);
        }
    }

    private class InsertPeopleTimerTask extends TimerTask {

        public void run() {
            AnimationObject person = new AnimationObject(32, 24, "/Images/HinhNguoi.png", 100);
            person.Start(true);
            
            int y = r.nextInt(getHeight() - viewMargin_Top);
            person.currentX = 0;
            person.currentY = person.height - getHeight() - viewMargin_Top;
            lstPerson[currentTotalPerson++] = person;
            layerManager.insert(person.objSprite, 0);
        }
    }

    private void UpdatePeoplePos() {
        for (int i = 0; i < currentTotalPerson; i++) {
            lstPerson[i].currentY += arrStageInfo[curStage].carSpeed;
            lstPerson[i].currentX += 1;
            //if (lstPerson[i].currentY < getHeight() + 10 ) {
            if (lstPerson[i].currentX < getWidth() - 60) {
                lstPerson[i].SetCurrentPos(lstPerson[i].currentX, lstPerson[i].currentY);
            } else {
                //Remove money
                layerManager.remove(lstPerson[i].objSprite);
                for (int j = i; j < currentTotalPerson - 1; j++) {
                    lstPerson[j] = lstPerson[j + 1];
                }
                lstPerson[currentTotalPerson - 1].Stop();
                lstPerson[currentTotalPerson - 1] = null;
                currentTotalPerson -= 1;
                i--;
            }
        }

    }

    private TiledLayer InitTiledBackground(String imgSrc, int tileData[], int totalRows, int totalCols, int tileWidth,
            int tileHeight) {
        try {
            Image tileImages = Image.createImage(imgSrc);
            TiledLayer tiledLayer = new TiledLayer(totalCols, totalRows, tileImages, tileWidth, tileHeight);
            for (int i = 0; i < tileData.length; i++) {
                int column = i % totalCols;
                int row = i / totalCols;
                tiledLayer.setCell(column, row, tileData[i]);
            }
            return tiledLayer;
        } catch (Exception ex) {
            return null;
        }
    }

    //---------------duong
    private void showReady() {
        boolean ready = true;
        int count = 0;
        while (ready) {
            count++;
            switch (count) {
                case 1:
                    drawImage("/Images/ready.png", getWidth() / 2 - 40, getHeight() / 2 - 20);
                    break;
                case 2:
                    drawImage("/Images/3.png", getWidth() / 2, getHeight() / 2);
                    break;
                case 3:
                    drawImage("/Images/2.png", getWidth() / 2, getHeight() / 2);
                    break;
                case 4:
                    drawImage("/Images/1.png", getWidth() / 2, getHeight() / 2);
                    ready = false;
                    break;
            }
            try {
                Thread.sleep(700);
            } catch (InterruptedException ie) {
            }
        }
    }

    private void drawImage(String imageSource, int x, int y) {
        g.setColor(0x017728);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0xff0000);

        layerManager.paint(g, viewMargin_Left, viewMargin_Top);
        layerManager_Left.paint(g, 0, 0);

        Image image = null;
        try {
            image = Image.createImage(imageSource);
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.g.drawImage(image, x, y, Graphics.LEFT | Graphics.TOP);
        flushGraphics();
    }

    private void showGameOver() {
        g.setColor(0x000000);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0xff0000);
        try {
            Image imgGameover = Image.createImage("/Images/GameOver.png");
            g.drawImage(imgGameover, getWidth() / 2, getHeight() / 2 - 50, Graphics.HCENTER | Graphics.VCENTER);
            g.drawString("Your Score is:" + Integer.toString(totalMoney), 40, 200, Graphics.TOP | Graphics.LEFT);
            g.drawString("Press ENTER to go back menu", 10, 230, Graphics.TOP | Graphics.LEFT);
            flushGraphics();
            HighScore hs = new HighScore();
            hs.saveScore(totalMoney);
            while(true){
                if ((getKeyStates() & FIRE_PRESSED) != 0) {
                    soundHelper.stopSound();
                    soundCollidePeople.stopSound();
                    soundExplode.stopSound();
                    soundGetItem.stopSound();
                    soundPhanh.stopSound();
                    curStage = 0;
                    totalMoney = 0;
                    life = 3;
                    InitStagesInfo();
                    Init();
                    this.midlet.showMenuGame();
                    return;
                }
            }
        } catch (Exception ex) {
        }
    }
    
    private void showWinner() {
        g.setColor(0x000000);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0xff0000);
        try {
            Image imgGameover = Image.createImage("/Images/Winner.png");
            g.drawImage(imgGameover, getWidth() / 2, getHeight() / 2 - 50, Graphics.HCENTER | Graphics.VCENTER);
            g.drawString("Your Score is:" + Integer.toString(totalMoney), 40, 200, Graphics.TOP | Graphics.LEFT);
            g.drawString("Press ENTER to go back menu", 10, 230, Graphics.TOP | Graphics.LEFT);
            flushGraphics();
            HighScore hs = new HighScore();
            hs.saveScore(totalMoney);
            while(true){
                if ((getKeyStates() & FIRE_PRESSED) != 0) {
                    soundHelper.stopSound();
                    soundCollidePeople.stopSound();
                    soundExplode.stopSound();
                    soundGetItem.stopSound();
                    soundPhanh.stopSound();
                    curStage = 0;
                    totalMoney = 0;
                    life = 3;
                    InitStagesInfo();
                    Init();
                    this.midlet.showMenuGame();
                    return;
                }
            }
        } catch (Exception ex) {
        }
    }
}
